Selektion zur Berechtigung

Berechtigungen und die dazugehörigen Berechtigungsprüfungen sind eine mitunter eine knifflige Angelegenheit. Bei einzelnen Werten ist es einfach, diese mit der entsprechenden Berechtigung zu prüfen. Wenn es jedoch um Selektionen geht, bei denen der Anwender nur die Berechtigung über einen Teil der Daten hat, dann wird es schon schwieriger…

Problem – Selektionsoptionen

Bei dem hier beschriebenen Problem hat der Anwender bei einem Report die Möglichkeit, ein Objekt über Selektionsoptionen (SELECT-OPTIONS) einzugrenzen. Hierfür muss ich jedoch wissen, welches die zu Grunde liegende Prüftabelle mit allen existierenden Daten ist.

Beispiel Verkaufsorganisation

Der Anwender selektiert Verkaufsorganisationen A* und B*. Der Anwender hat jedoch nur die Berechtigung für A200 und B330.

In der Prüftabelle für die Verkaufsorganisationen (Tabelle TVAK) sind die folgenden Verkaufsorganisationen gepflegt:

VkorgBezeichnung
A100Deutschland Gebiet Nord
A200Deutschland Gebiet Süd
A300Deutschland Gebiet West
A400Deutschland Gebiet Ost
B330Nord-Italien
B340Süd-Italien
C500Spanien

Lösung A – Vorselektion

Bei dieser Lösungsvariante wird vorab geprüft, für welche Objekte der Anwender die Berechtigung hat. Man würde also die tatsächlich vorhandenen Einträge aus der Prüftabelle selektieren und für jeden Eintrag prüfen, ob der Anwender die entsprechende Berechtigung hat.

Mit den verbleibenden Einträgen kann man entweder eine dynamische WHERE-Bedingung bauen oder baut aus diesen Einträgen eine genaue Ranges-Tabelle auf.

Lösung B – Einzelprüfung der Daten

Es gibt natürlich auch die relativ einfache Möglichkeit, alle Daten einzulesen und dann bei jedem einzelnen Datensatz zu prüfen, ob der Anwender berechtigt ist, ihn zu sehen. Das ist einfach zu programmieren, kann jedoch bei großen Datenmengen ein erhebliches Laufzeitproblem werden.

Unterstützung

Durch Zufall bin ich auf die Klasse CL_AUTH_OBJECTS_TO_SQL gestoßen. Mit Hilfe dieser Klasse wird der Lösungsweg A eingeschlagen. Allerdings ohne, dass ich als Programmierer wissen müsste, welches die Zugrunde liegende Prüftabelle ist und ohne, dass ich die WHERE-Bedingung selber erstellen müsste.

Der Klasse müssen folgende Daten übergeben werden:

  • das zu prüfende Berechtigungsobjekt
  • die Aktivität (Anzeigen, Ändern, Löschen etc)
  • Ein Field Mapping (DDIC-Grundlage der Felder)
  • optional: Filter für die Einschränkung auf Objekte

Mit GET_SQL_CONDITION bekommt man dann die WHERE-Bedingung für die Felder zurück, für die der Anwender eine Berechtigung hat.

Folgendes kleine Beispiel zeigt die Anwendung für die Klasse.

Code

DATA h_vkorg TYPE vkorg.
SELECT-OPTIONS s_vkorg FOR h_vkorg DEFAULT 'A100'.

START-OF-SELECTION.

  DATA(lo_converter_osql) = cl_auth_objects_to_sql=>create_for_open_sql( ).

  lo_converter_osql->add_authorization_object( 
    iv_authorization_object = 'V_VBAK_VKO'
    it_activities = VALUE #(
             ( auth_field = 'ACTVT' value = '03' ) )
    it_field_mapping = VALUE #(
             ( auth_field = 'VKORG'
               view_field = VALUE #(
                               table_ddic_name = 'VBAK'
                               table_alias     = ''
                               field_name      = 'VKORG' ) ) )
    it_filter = VALUE #( FOR selopt IN s_vkorg[]
             ( auth_field = 'VKORG' low = selopt-low high = selopt-high ) ) ).
  
  TRY.
      DATA(lv_where_clause) = lo_converter_osql->get_sql_condition( ).
      IF lv_where_clause IS INITIAL.
        MESSAGE 'Du hast die Berechtigung für alle ausgewählten Verkaufsorganisationen' TYPE 'I'.
      ELSE.
        cl_demo_output=>display_text( |Deine WHERE-Bedingung: { lv_where_clause }| ).
      ENDIF.
    CATCH cx_auth_not_authorized.
      MESSAGE 'Keine Berechtigung für die ausgewählten Verkaufsorganisationen' TYPE 'I'.
  ENDTRY.
Enno Wulff